package com.cartoonrabbit.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cartoonrabbit.consts.TransferStatus;
import com.cartoonrabbit.consts.WxAPIURL;
import com.cartoonrabbit.pojo.User;
import com.cartoonrabbit.pojo.WithdrawOrder;
import com.cartoonrabbit.mapper.WithdrawOrderMapper;
import com.cartoonrabbit.service.IUserService;
import com.cartoonrabbit.service.IWithdrawOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cartoonrabbit.vo.RespBean;
import com.cartoonrabbit.vo.RespPageBean;
import com.cartoonrabbit.wxapp.properties.WxAppInfoProperties;
import com.cartoonrabbit.wxapp.utils.PrimaryKeyUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.Principal;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author LiuTeng
 * @since 2023-01-09
 */
@Service
public class WithdrawOrderServiceImpl extends ServiceImpl<WithdrawOrderMapper, WithdrawOrder> implements IWithdrawOrderService {

    @Autowired
    private WxAppInfoProperties wxAppInfoProperties;

    @Autowired
    private CloseableHttpClient closeableHttpClient;
    @Autowired
    private IUserService userService;


    @Override
    public RespBean transfer(Long money, Principal principal) {

        // 判断钱是否符合格式
        if (money<30){
            return RespBean.fail("请输入大于0.3元的金额");
        }
        // 获取用户账户信息
        String openId=principal.getName();
        User user = userService.getById(openId);
        // 判断提现金钱是否在用户账户余额范围之内
        if (user.getBalance()<money){
            return RespBean.fail("提现金额大于用户余额");
        }
        // 生成提现记录
        WithdrawOrder withdrawOrder = new WithdrawOrder();
        withdrawOrder.setWithdrawId(PrimaryKeyUtils.getTransferNo());
        withdrawOrder.setWithdrawName("端麟网络工作室转账");
        withdrawOrder.setWithdrawRemark("卡通兔活动余额提现");
        withdrawOrder.setWithdrawMoney(money);
        withdrawOrder.setOpenId(openId);
        withdrawOrder.setStatus(TransferStatus.GOING);
        // 开始调用微信余额提现接口
        HttpPost httpPost = new HttpPost(WxAPIURL.TRANSFER);
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();
        JSONObject jsonObject = new JSONObject();
        jsonObject.putOnce("appid", wxAppInfoProperties.getAppId())
                .putOnce("out_batch_no", withdrawOrder.getWithdrawId())
                .putOnce("batch_name", withdrawOrder.getWithdrawName())
                .putOnce("batch_remark", withdrawOrder.getWithdrawRemark())
                .putOnce("total_amount", money.intValue())
                .putOnce("total_num", 1);
        JSONArray objects = new JSONArray();
        JSONObject jsonObject1 = new JSONObject();
        jsonObject1.putOnce("out_detail_no",withdrawOrder.getWithdrawId());
        jsonObject1.putOnce("transfer_amount",money.intValue());
        jsonObject1.putOnce("transfer_remark",withdrawOrder.getWithdrawRemark());
        jsonObject1.putOnce("openid",openId);
        objects.put(jsonObject1);
        jsonObject.putOnce("transfer_detail_list",objects);
        try {
            objectMapper.writeValue(bos,jsonObject);
        } catch (IOException e) {
            return RespBean.fail("服务器异常601");
        }
        httpPost.setEntity(new StringEntity(JSONUtil.toJsonStr(jsonObject), "UTF-8"));
        CloseableHttpResponse response = null;
        try {
            response = closeableHttpClient.execute(httpPost);
        } catch (IOException e) {
            return RespBean.fail("服务器异常602");
        }
        String bodyAsString = null;
        try {
            bodyAsString = EntityUtils.toString(response.getEntity());
        } catch (IOException e) {
            return RespBean.fail("服务器异常603");
        }
        // 解析返回字符串
        JSONObject entries = JSONUtil.parseObj(bodyAsString);
        String batch_id = entries.getStr("batch_id");
        if (batch_id==null){
            return RespBean.fail("商户异常，转账失败");
        }
        withdrawOrder.setTransferId(batch_id);
        // 更新用户余额
        userService.update(new UpdateWrapper<User>().eq("open_id",user.getOpenId()).set("balance",user.getBalance()-money));
        // 新增转账记录
        save(withdrawOrder);
        user.setBalance(user.getBalance()-money);
        return RespBean.success("SUCCESS",user);
    }

    @Override
    public void checkTransferStatus(WithdrawOrder transfer) throws IOException {
        if (transfer==null){
            return;
        }
        if (transfer.getStatus()==TransferStatus.GOING){
            String url=String.format(WxAPIURL.BATCHESDETAIL,transfer.getWithdrawId(),transfer.getWithdrawId());
            // 开始调用微信余额提现接口
            HttpGet httpGet = new HttpGet(url);
            httpGet.addHeader("Content-type","application/json; charset=utf-8");
            httpGet.addHeader("Accept", "application/json");
            CloseableHttpResponse response = null;
            response = closeableHttpClient.execute(httpGet);
            String bodyAsString =  EntityUtils.toString(response.getEntity());
            // 解析返回字符串
            JSONObject entries = JSONUtil.parseObj(bodyAsString);
            String detail_status = entries.getStr("detail_status");
            if (detail_status==null||detail_status.equals("PROCESSING")){
                return;
            }
            User user = userService.getById(transfer.getOpenId());
            if (detail_status.equals("FAIL")){// 转账失败
                // 修改用户余额信息
                userService.update(new UpdateWrapper<User>().eq("open_id",user.getOpenId()).set("balance",user.getBalance()+transfer.getWithdrawMoney()));
                // 修改用户转账信息
                transfer.setStatus(TransferStatus.FAIL);
                updateById(transfer);
                return;
            }
            // 修改用户转账信息
            transfer.setStatus(TransferStatus.SUCCESS);
            updateById(transfer);
        }else {
            return;
        }
    }

    @Override
    public RespBean getWithdrawOrderList(Integer currentPage, Integer size, String name) {
        Page page=new Page(currentPage,size);
        Page<WithdrawOrder> withdrawOrderPage=page(page,new QueryWrapper<WithdrawOrder>().eq("open_id",name));
        RespPageBean respPageBean = new RespPageBean();
        respPageBean.setCurrentPage(withdrawOrderPage.getCurrent());
        respPageBean.setSize(withdrawOrderPage.getSize());
        respPageBean.setTotal(withdrawOrderPage.getTotal());
        respPageBean.setData(withdrawOrderPage.getRecords());
        return RespBean.success("SUCCESS",respPageBean);
    }
}
